package cn.xinfei.xdecision.engine.runner.context;

import cn.xinfei.xdecision.common.model.datax.enums.VariableEnum;
import cn.xinfei.xdecision.common.utils.constant.CommonConst;
import cn.xinfei.xdecision.common.utils.constant.runner.ParamTypeConst;
import cn.xinfei.xdecision.common.utils.util.CollectionUtil;
import cn.xinfei.xdecision.common.vo.FieldInfoVo;
import cn.xinfei.xdecision.conf.ApplicationContextUtil;
import cn.xinfei.xdecision.engine.runner.datax.DataRealCollectHandler;
import cn.xinfei.xdecision.engine.runner.datax.RiskDataApiAdapter;
import cn.xinfei.xdecision.engine.runner.metadata.MetadataProvider;
import cn.xinfei.xdecision.nacos.NacosSwitchProperties;
import cn.xinfei.xdecision.util.DataValueCastUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * 获取变量值的统一入口
 */
@Slf4j
public class AmmunitionDepot {


    public static final String REMOTE="REMOTE";
    public static final String LOCAL="LOCAL";

    private static DataRealCollectHandler dataRealCollectHandler;

    /**
     * 变量值转义
     *
     * @param fieldTypeMap
     * @param contextValue
     * @return
     */
    public static Map<String, Object> convertVariables(Map<String, Integer> fieldTypeMap, Map<String, Object> contextValue) {
        if (!CollectionUtil.isNotNullOrEmpty(fieldTypeMap)) {
            return contextValue;
        }
        Map<String, Object> inputParamValues = new HashMap<>();
        if (CollectionUtil.isNotNullOrEmpty(contextValue)) {
            String key = "";
            Integer valueType = null;
            for (Map.Entry<String, Integer> entry : fieldTypeMap.entrySet()) {
                key = entry.getKey();
                valueType = entry.getValue();
                if (valueType == null) {
                    continue;
                }
                //2代表字符串
                Object o = contextValue.get(key);
                if (o == null) {
                    log.warn("variable is null,key={},valueType={}", key, valueType);
                    continue;
                }

                //String
                if (valueType == ParamTypeConst.VARIABLE) {

                    String variableValue = CommonConst.SYMBOL_SINGLE_QUOTA + o.toString() + CommonConst.SYMBOL_SINGLE_QUOTA;
                    contextValue.put(key, variableValue);
                    inputParamValues.put(key, variableValue);
                } else {
                    //integer(1),string(2),boolean(3),double(4)
                    Object value = DataValueCastUtils.cast(key, o.toString(), valueType);
                    if (null != value) {
                        contextValue.put(key, value);
                        inputParamValues.put(key, value);
                    } else {
                        log.warn("cast value result is null,key={},value={},valueType={}", key, o, valueType);
                    }
                }

            }
        }
        return inputParamValues;
    }


    //根据key，分不同类型取出值
    public final static Object getValueByKeyFromRemote(String fieldCode) {
        return getValueByKeyFromRemote(ParamTypeConst.VARIABLE, fieldCode, null);
    }

    public final static Object getValueByKeyFromRemote(Integer variableType, String fieldCode, String fieldValue) {
        return getValueByKey( variableType,  fieldCode,  fieldValue, AmmunitionDepot.REMOTE);
    }
    public final static Object getValueByKeyFromContext(Integer variableType, String fieldCode, String fieldValue) {
        return getValueByKey( variableType,  fieldCode,  fieldValue, AmmunitionDepot.LOCAL);
    }
    private final static Object getValueByKey(Integer variableType, String fieldCode, String fieldValue,String source) {
        Object result = fieldCode;
        FieldInfoVo fieldInfoVo = null;
        if (variableType != null) {
            switch (variableType) {
                case ParamTypeConst.CONSTANT:
                    //常量类型
                    result = fieldValue;
                    fieldInfoVo = MetadataProvider.fieldMapCache.get(fieldCode);
                    break;
                case ParamTypeConst.VARIABLE:
                    //变量类型
                    result = getValueFromDataServer(fieldCode,source);
                    fieldInfoVo = MetadataProvider.fieldMapCache.get(fieldCode);
                    break;
            }
        }

        if ((result == null) && null != fieldInfoVo) {
            if (Objects.equals(fieldInfoVo.getVarTypeId(), VariableEnum.CONSTANT_VAR.getCode())) {
                result = fieldInfoVo.getConstValue();
            } else {
                result = fieldInfoVo.getVarDefaultValue();
            }
            log.info("return default，fieldCode={},fieldValue={},default={}", fieldCode, fieldValue, result);
        }

        if ((result != null) && fieldInfoVo != null) {
            Integer valueType = fieldInfoVo.getValueType();
            result = DataValueCastUtils.cast(fieldInfoVo.getFieldCode(), result.toString(), valueType);
        } else {
            log.warn("value is null... variableType={}, fieldCode={},  fieldValue={}", variableType, fieldCode, fieldValue);
        }
        return result;
    }


    private static Object getValueFromDataServer(String fieldCode,String source) {

        Object result = PipelineContextHolder.getValueByKey(fieldCode);
        if (result != null) {
            if (NacosSwitchProperties.getNacosSwitchProperties().isDebugLog()) {
                log.info("getValueByKey, type=context,{}={}", fieldCode, result);
            }
            return result;
        }


        FieldInfoVo fieldInfoVo = MetadataProvider.fieldMapCache.get(fieldCode);
        String varTypeId = fieldInfoVo.getVarTypeId();
        //只请求数据源变量，衍生变量和接口变量。其余变量取默认值或者常量值
        if (REMOTE.equals(source)&&
                (Objects.equals(varTypeId, VariableEnum.DATABASE_VAR.getCode())
                || Objects.equals(varTypeId, VariableEnum.DERIVE_VAR.getCode())
                || Objects.equals(varTypeId, VariableEnum.INTERFACE_VAR.getCode()))) {
            if (dataRealCollectHandler == null) {
                dataRealCollectHandler = ApplicationContextUtil.getBean(DataRealCollectHandler.class);
            }
            Set<String> fetchField = new HashSet<>();
            try {
                fetchField.add(fieldCode);
                Boolean aBoolean = dataRealCollectHandler.queryFieldValue(fetchField, RiskDataApiAdapter.CollectTypeEnum.REAL.toString());
                if (aBoolean) {
                    Object valueByKey = PipelineContextHolder.getValueByKey(fieldCode);
                    log.info("getValueByKey, type=remote,{}={}", fieldCode, result);
                    return valueByKey;
                }
            } catch (Exception exception) {
                exception.printStackTrace();
            }
        }
        return null;
    }
    //根据key，分不同类型取出值
//    public final static Object getValueByKey(Integer variableType, String fieldCode) throws EvaluationException {
//        return getValueByKey(variableType, fieldCode, null);
//    }


    //根据key，分不同类型取出值
  /*
 public final static Object getValueByKey(Integer variableType, String fieldCode, List<JSONObject> list) throws EvaluationException {
        Object result = fieldCode;
        if (variableType != null) {
            switch (variableType) {
                case ParamTypeConst.CONSTANT:
                    //常量类型
                    result = fieldCode;
                    break;
                case ParamTypeConst.VARIABLE:
                    //变量类型
                    result = PipelineContextHolder.getValueByKey(fieldCode);
                    break;
                case ParamTypeConst.CUSTOM:
                    //自定义脚本类型
                    Map<String, FieldInfoVo> fieldFromExpressField = null;
                    if (list == null || list.isEmpty()) {
                        fieldFromExpressField = ExpressExecutor.getFieldFromExpressField(fieldCode);
                    } else {
                        fieldFromExpressField = ExpressExecutor.getFieldFromExpressField(fieldCode, list);
                    }
                    JSONObject formulaJson = JSON.parseObject(fieldCode);
                    result = ScriptExecutor.executeScript(formulaJson, fieldFromExpressField);
                    break;
                case ParamTypeConst.REGEX:
                    //正则表达式类型
                    ConcurrentMap<String, Object> contextValue = PipelineContextHolder.getContextValue();
                    result = RegexExecutor.getObjFromRegex(contextValue, fieldCode);
            }
        }
        return result;
    }
    */
}
